/**
 * @filename:InspectServiceImpl Jan 15, 2025
 * @project Wonder Vue Admin Api  1.1.0
 * Copyright(c) 2022 Wonder Co. Ltd. 
 * All right reserved. 
 */
package com.wonder.app.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import com.vtuzx.core.bean.dto.VtuzxMap;
import com.vtuzx.core.utils.VtuzxUtil;
import com.wonder.admin.domain.SysAdmin;
import com.wonder.admin.service.IVtuzxKingdeeService;
import com.wonder.app.domain.*;
import com.wonder.app.domain.Receivedetail;
import com.wonder.app.mapper.*;
import com.wonder.app.service.*;
import com.wonder.app.request.InspectRequest;
import com.wonder.bean.kingdee.VtuzxKingdeeCloudClient;
import com.wonder.bean.kingdee.xqc.VtuzxArrayList;
import com.wonder.common.utils.StringUtils;
import com.wonder.common.utils.MessageUtils;
import com.wonder.common.common.AjaxResult;

import java.util.*;

import com.wonder.constant.BillType;
import com.wonder.constant.IXqcConst;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import javax.servlet.http.HttpServletRequest;

/**   
 * @Description:TODO(来料检验单服务实现)
 *
 * @version: 1.1.0
 * @author: Wonder
 * 
 */
@Service
public class InspectServiceImpl  extends ServiceImpl<InspectDao, Inspect> implements InspectService  {
	/** 日志 */
	private static final Logger _logger = LoggerFactory.getLogger(InspectServiceImpl.class);

	@Autowired
	private InspectDao inspectDao;

	@Autowired
	private InspectDetailDao inspectDetailDao;

	@Autowired
	private IVtuzxKingdeeService vtuzxKingdeeService;

	@Autowired
	private ReceiveDao receiveDao;

	@Autowired
	private ReceivedetailDao receivedetailDao;

	@Autowired
	private PurInService purInService;

	@Autowired
	private ReceivedetailService receivedetailService;

	@Autowired
	private ReceiveService receiveService;

	@Autowired
	private YzjService yzjService;

    /**
     * 验证来料检验单信息
     * 
     * @param inspect
     * @param type
     * @return String
     */
	@Autowired
	private PurInspectDetailService purInspectDetailService;
	@Autowired
	private PurInspectDetailDao purInspectDetailDao;
	@Autowired
	private InspectService inspectServicel;

	@Autowired
	private MaterialDao materialDao;

	@Autowired
	private InspectService inspectService;

	@Autowired
	private InspectDetailService inspectDetailService;




	@Override
    public String validate(Inspect inspect,String type){
    
    
       return "";
    }
    
    
    /**
	 * Description:来料检验单分页返回
	 * @param request //检索条件
	 * @param page //分页参数
	 * @return IPage<Inspect>   //分页记录
	 */
	@Override 
	public IPage<Inspect> selectList(InspectRequest request, Page<Inspect> page){
	    LambdaQueryWrapper<Inspect> lambdaQueryWrapper = new LambdaQueryWrapper<>();
	    
	    if (null != request.getId()) {
	       lambdaQueryWrapper.eq(Inspect::getId, request.getId());
	      }
		if (StringUtils.hasText(request.getBillNo())) {
			lambdaQueryWrapper.like(Inspect::getBillNo, request.getBillNo());
		}
		if (StringUtils.hasText(request.getReceiveBillNo())) {
			lambdaQueryWrapper.like(Inspect::getReceiveBillNo, request.getReceiveBillNo());
		}
		if (StringUtils.hasText(request.getPurChaser())) {
			lambdaQueryWrapper.like(Inspect::getPurChaser, request.getPurChaser());
		}

		if (StringUtils.hasText(request.getInspectUser())) {
			lambdaQueryWrapper.like(Inspect::getInspectUser, request.getInspectUser());
		}
		if (StringUtils.hasText(request.getSupplierName())) {
			lambdaQueryWrapper.like(Inspect::getSupplierName, request.getSupplierName());
		}
		if (StringUtils.hasText(request.getCreateUserName())) {
			lambdaQueryWrapper.like(Inspect::getCreateUserName, request.getCreateUserName());
		}
		if (request.getCreateTime() != null) {
			Date[] fCREATEDATE = request.getCreateTime();
			if (fCREATEDATE.length > 0) {
				// 设置开始时间为当天的零点
				Calendar startCalendar = Calendar.getInstance();
				startCalendar.setTime(fCREATEDATE[0]);
				startCalendar.set(Calendar.HOUR_OF_DAY, 0);
				startCalendar.set(Calendar.MINUTE, 0);
				startCalendar.set(Calendar.SECOND, 0);
				startCalendar.set(Calendar.MILLISECOND, 0);
				Date startDate = startCalendar.getTime();
				lambdaQueryWrapper.ge(Inspect::getCreateTime, startDate);
			}
			if (fCREATEDATE.length == 2) {
				// 设置结束时间为当天的24点
				Calendar endCalendar = Calendar.getInstance();
				endCalendar.setTime(fCREATEDATE[1]);
				endCalendar.set(Calendar.HOUR_OF_DAY, 23);
				endCalendar.set(Calendar.MINUTE, 59);
				endCalendar.set(Calendar.SECOND, 59);
				endCalendar.set(Calendar.MILLISECOND, 999);
				Date endDate = endCalendar.getTime();
				lambdaQueryWrapper.le(Inspect::getCreateTime, endDate);
			}
		}
		if (null != request.getStockNo()) {
			String stockNo = request.getStockNo().replace("'", "''"); // 防注入
			lambdaQueryWrapper.inSql(Inspect::getBillNo,
					"SELECT BillNo FROM t_pur_inspect_detail WHERE StockNo = '" + stockNo + "'");
		}
		if (!VtuzxUtil.isEmpty(request.getStatus())) {
			lambdaQueryWrapper.eq(Inspect::getStatus,request.getStatus());
		}
		lambdaQueryWrapper.orderByDesc(Inspect::getCreateTime);
		Page<Inspect> selectPage = this.baseMapper.selectPage(page, lambdaQueryWrapper);
		return selectPage;
    }
	/**
	 * receive详情
	 * @param map
	 * @return
	 * @throws Exception
	 */
	@Override
	public Map<String, Object> getInspectDetail(Map<String, Object> map) throws Exception{
		String billNo = map.get("billNo").toString();
		Inspect inspectform = inspectDao.selectOne(new LambdaQueryWrapper<Inspect>()
				.eq(Inspect::getBillNo,billNo));
		if (null == inspectform){
			throw new RuntimeException("单号错误请重试");
		}
		List<InspectDetail> inspectList = inspectDetailDao.selectList(new LambdaQueryWrapper<InspectDetail>()
				.eq(InspectDetail::getBillNo,billNo));
		Map<String,Object> data = new HashMap<>();
		data.put("data",inspectform);
		data.put("dataList",inspectList);
		return data;
	}

	/**
	 * 生成来料检验单(手机端)
	 * @param userName
	 * @param map
	 * @return
	 */
	@Override
	public boolean saveInspect(Long user_id, String  userName, Map<String, Object> map) throws Exception{
		String receiveBillNo = VtuzxUtil.getString(map,"billNo");//收料通知单号
		String remark = VtuzxUtil.getString(map,"remark");//备注
		List<Map<String,Object>> detailList = VtuzxUtil.getObject(map,"detail");
		Receive receive = receiveDao.selectOne(new LambdaQueryWrapper<Receive>().eq(Receive::getBillNo, receiveBillNo));
		//添加备注信息
		if (!VtuzxUtil.isEmpty(receive)){
			receive.setRemark(remark);
			receiveDao.updateById(receive);
		}
		List<Long> idList = new ArrayList<>();
		List<InspectDetail> inspectDetails = new ArrayList<>();
		List<Inspect> headList = new ArrayList<>();//单据头集合
		String pectBillNo = IXqcConst.createBillNo(BillType.LLJY);//生成来料检验单号
		//添加详情数据
		for (Map<String,Object> detailMap : detailList ){
			String materialNo = VtuzxUtil.getString(detailMap,"materialNumber");
			String materialName = VtuzxUtil.getString(detailMap,"materialName");
			String specification = VtuzxUtil.getString(detailMap,"specification");
			String unitName = VtuzxUtil.getString(detailMap,"unitName");
			String unitNumber = VtuzxUtil.getString(detailMap,"unitNumber");
			String fAuxUnitNo = VtuzxUtil.getString(detailMap,"fAuxUnitNo");
			String fAuxUnitName = VtuzxUtil.getString(detailMap,"fAuxUnitName");
			String stockNo = VtuzxUtil.getString(detailMap,"stockNumber");
			String stockName = VtuzxUtil.getString(detailMap,"stockName");
			Boolean isBatch = VtuzxUtil.getBoolean(detailMap,"isBatch");//是否启用批号
			String lot = VtuzxUtil.getString(detailMap,"lot");
			//金蝶查询如果启用批号并且没有批号的话给与提示
			if (isBatch && VtuzxUtil.isEmpty(lot)){
				throw new RuntimeException(String.format("物料编码:%s,启用批号，请输入",materialNo));
			}
			//如果没有启用批号的话批号不管填没填都默认空
			if (!isBatch){
				lot = "";
			}

			Double count = VtuzxUtil.getDouble(detailMap,"weightResultQty");//实际收货重量
			Long id = VtuzxUtil.getLong(detailMap,"id");
			if (!idList.contains(id)){
				idList.add(id);
			}

			InspectDetail detail = new InspectDetail();//来料检验单单据体
			detail.setBillNo(pectBillNo);
			detail.setMaterialName(materialName);
			detail.setMaterialNo(materialNo);
			detail.setSpecification(specification);
			detail.setUnitName(unitName);
			detail.setUnitNo(unitNumber);
			detail.setFlot(lot);
			detail.setInspectQty(count);//检验数量
			detail.setUnqualifiedQty(0.0);//不合格数量
			detail.setQualifiedQty(count);//合格数量
			detail.setFAuxUnitName(fAuxUnitName);
			detail.setFAuxUnitNo(fAuxUnitNo);
			detail.setIsChecked(false);//是否质检
			detail.setReceiveBillNo(receiveBillNo);
			detail.setIsAbnomal(false);//是否异常
			detail.setStockName(stockName);
			detail.setStockNo(stockNo);
			detail.setReveiveId(id);//收料详情的Id
			inspectDetails.add(detail);
		}
		Inspect inspect = new Inspect();//来料检验单单据头
		inspect.setBillNo(pectBillNo);
		inspect.setReceiveBillNo(receiveBillNo);
		inspect.setSupplierName(receive.getSupplierName());
		inspect.setSupplierNo(receive.getSupplierNo());
		inspect.setPurChaser(receive.getPurChaser());
		inspect.setCreateTime(new DateTime());
		inspect.setStatus("save");
		inspect.setCreateUserName(userName);//创建人
		inspect.setRemark(remark);//备注
		headList.add(inspect);
		//数据库添加数据
		boolean headRes = inspectService.saveOrUpdateBatch(headList);
		boolean detailRes = inspectDetailService.saveOrUpdateBatch(inspectDetails);
		//修改收料详情表为已经下推来料检验
		List<Receivedetail> receivedetails = receivedetailDao.selectList(new LambdaQueryWrapper<Receivedetail>()
				.in(Receivedetail::getId, idList));
		for (Receivedetail receivedetail : receivedetails){
			receivedetail.setIsChecked(true);
		}
		//校验交货数量是否等于下推数量
		Boolean aBoolean1 = cheackReceiveDettailCount(receivedetails);
		//校验收料详情是否都关闭
		Boolean aBoolean = cheackReceive(receiveBillNo);
		//如果都下推的话修改单据头的字段
		if (aBoolean){
			receive.setIsChecked(true);
			receiveService.updateById(receive);
		}
		//调用设审核来料检验单
		Map<String,Object> inspectMap = new HashMap<>();
		inspectMap.put("billNo",pectBillNo);
		try {
			auditInspect(user_id,userName,inspectMap);
		} catch (Exception e){
			throw new RuntimeException(e.getMessage());
		}

		//给质检部发送通知
		try {
			Map<String,Object> data = new HashMap<>();
			data.put("billNo",pectBillNo);
			yzjService.sendMsgToQuality(data,BillType.LLJY.label());
		} catch (Exception e){

		}


		return headRes && detailRes;
	}


	/**
	 * 判断物料是否启用批号
	 * @param materialNo
	 * @return
	 */
	private Boolean materialIsFlot(String materialNo) throws Exception{
		VtuzxKingdeeCloudClient client = vtuzxKingdeeService.loginKingdee();
		Boolean FIsBatchManage = false;
		//查询物料是够启用批号
		List<VtuzxMap> materialQuery = vtuzxKingdeeService.query(client, "BD_MATERIAL", new VtuzxArrayList<>(
						"FIsBatchManage"//是否启用批号
				),
				String.format("FNumber = '%s'", materialNo), null, 0, 1);
		if (!VtuzxUtil.isEmpty(materialQuery)) {
			FIsBatchManage = VtuzxUtil.getBoolean(materialQuery.get(0),"FIsBatchManage");
		}
		return FIsBatchManage;
	}


	/**
	 * 判断收料通知单详情是否都已经下推来料检验(如果交货数量等于下推数量关闭当前行)
	 * @param
	 * @return
	 */
	private Boolean cheackReceiveDettailCount(List<Receivedetail> receivedetailList){
		String billNo = receivedetailList.get(0).getBillNo();

//		查询已经下推的来料检验单，计算下推的物料数量
		List<Inspect> inspects = inspectDao.selectList(new LambdaQueryWrapper<Inspect>()
				.eq(Inspect::getReceiveBillNo, billNo));
		List<String> inspectNoList = new ArrayList<>();
		Map<String,Object> materialMap = new HashMap<>();//key收料详情Id val:数量
		if (null != inspects && inspects.size() > 0){
			for (Inspect inspect : inspects){
				String billNo1 = inspect.getBillNo();
				if (!inspectNoList.contains(billNo1)){
					inspectNoList.add(billNo1);
				}
			}
			List<InspectDetail> inspectDetails = inspectDetailDao.selectList(new LambdaQueryWrapper<InspectDetail>()
					.in(InspectDetail::getBillNo, inspectNoList));
			for (InspectDetail detail : inspectDetails){
//				String materialNo = detail.getMaterialNo();
				Long reveiveId = detail.getReveiveId();//收料详情id
				Double inspectQty = detail.getInspectQty();
				Double materialCount = VtuzxUtil.getDouble(materialMap,reveiveId.toString());
				materialMap.put(reveiveId.toString(),materialCount + inspectQty);
			}
		}
		//循环判断交货数量和已经下推的数量是否相等
		for (Receivedetail receivedetail : receivedetailList){
			Long id = receivedetail.getId();//收料详情id
//			String materialNo = receivedetail.getMaterialNumber();
			Double inspectCount = VtuzxUtil.getDouble(materialMap,id.toString());
			Double deliveQty = receivedetail.getDeliveQty();
			if (inspectCount.equals(deliveQty)){
				receivedetail.setIsClose(true);
			}
		}
		boolean res = receivedetailService.saveOrUpdateBatch(receivedetailList);
		return res;
	}


	/**
	 * 判断收料通知单详情是否都已经下推来料检验
	 * @param billNo
	 * @return
	 */
	private Boolean cheackReceive(String billNo){
		List<Receivedetail> detailList = receivedetailDao.selectList(new LambdaQueryWrapper<Receivedetail>()
				.eq(Receivedetail::getBillNo,billNo));

//		查询已经下推的来料检验单，计算下推的物料数量
//		List<Inspect> inspects = inspectDao.selectList(new LambdaQueryWrapper<Inspect>()
//				.eq(Inspect::getReceiveBillNo, billNo));
//		List<String> inspectNoList = new ArrayList<>();
//		Map<String,Object> materialMap = new HashMap<>();//key物料编码 val:数量
//		if (null != inspects && inspects.size() > 0){
//			for (Inspect inspect : inspects){
//				String billNo1 = inspect.getBillNo();
//				if (!inspectNoList.contains(billNo1)){
//					inspectNoList.add(billNo1);
//				}
//			}
//			List<InspectDetail> inspectDetails = inspectDetailDao.selectList(new LambdaQueryWrapper<InspectDetail>()
//					.in(InspectDetail::getBillNo, inspectNoList));
//			for (InspectDetail detail : inspectDetails){
//				String materialNo = detail.getMaterialNo();
//				Double inspectQty = detail.getInspectQty();
//				Double materialCount = VtuzxUtil.getDouble(materialMap,materialNo);
//				materialMap.put(materialNo,materialCount + inspectQty);
//			}
//		}
//		//循环判断交货数量和已经下推的数量是否相等
//		for (Receivedetail receivedetail : detailList){
//			String materialNo = receivedetail.getMaterialNumber();
//			Double inspectCount = VtuzxUtil.getDouble(materialMap,materialNo);
//			Double deliveQty = receivedetail.getDeliveQty();
//			if (!inspectCount.equals(deliveQty)){
//				return false;
//			}
//		}

		for (Receivedetail receivedetail : detailList){
			Boolean isClose = receivedetail.getIsClose();
			if (null == isClose){
				return false;
			}
			if (!isClose ){
				return isClose;
			}
		}
		return true;
 	}
	/**
	 * 来料检验单列表(手机端)
	 * @param map
	 * @return
	 */
	@Override
	public Map<String, Object> getInspectList(Map<String, Object> map) {
		int pageIndex = VtuzxUtil.getInt(map,"pageIndex");
		int pageSize = VtuzxUtil.getInt(map,"pageSize");
		String billNo = VtuzxUtil.getString(map,"billNo");//订单号
		String receiveBillNo = VtuzxUtil.getString(map,"receiveBillNo");//收料通知单号
		List<Receive> dataList = inspectDao.getInspectList(pageSize,pageIndex * pageSize,billNo,receiveBillNo);
		Map<String,Object> data = new HashMap<>();
		data.put("dataList",dataList);
		return data;
	}

	@Override
	public Map<String, Object> getInspectDetailPhone(Map<String, Object> map) throws Exception {
		String billNo = map.get("billNo").toString();
		Inspect inspectform = inspectDao.selectOne(new LambdaQueryWrapper<Inspect>()
				.eq(Inspect::getBillNo,billNo)
				.eq(Inspect::getStatus,"save"));
		if (null == inspectform){
			throw new RuntimeException("单号错误请重试");
		}
		List<InspectDetail> inspectList = inspectDetailDao.selectList(new LambdaQueryWrapper<InspectDetail>()
				.eq(InspectDetail::getBillNo,billNo));
		Map<String,Object> data = new HashMap<>();
		data.put("data",inspectform);
		data.put("dataList",inspectList);
		return data;
	}

	@Override
	public boolean changeInspectIsChecked(String userName, Map<String, Object> map) {
		boolean isChecked = VtuzxUtil.getBoolean(map,"isChecked");

		Map<String,Object> insMap = VtuzxUtil.getObject(map,"val");
		Long detailId = VtuzxUtil.getLong(insMap,"id");
		String remark = VtuzxUtil.getString(insMap,"remark");
		Double unqualifiedQty = VtuzxUtil.getDouble(insMap,"unqualifiedQty");//不合格数量
		Double qualifiedQty = VtuzxUtil.getDouble(insMap,"qualifiedQty");//合格数量
		InspectDetail detail = inspectDetailDao.selectById(detailId);
		detail.setUnqualifiedQty(unqualifiedQty);
		detail.setIsChecked(isChecked);
		detail.setQualifiedQty(qualifiedQty);
		detail.setRemark(remark);
		boolean res = inspectDetailService.updateById(detail);

		return res;
	}

	@Override
	public Boolean changeInspectReceive(JSONObject map) {
		_logger.info("修改来料检验"+ map.toString());
		JSONArray rceives = map.getJSONArray("AbnormalList");
		JSONObject receiveObj = (JSONObject) rceives.get(0);
		String abBillNo = receiveObj.getStr("abnomal");//异常单号
		String receiveBillNo = receiveObj.getStr("receive");//收料单号
		String trueOrfalse = receiveObj.getStr("trueOrfalse");//是否
		boolean res = false;
		InspectDetail detail = inspectDetailDao.selectOne(new LambdaQueryWrapper<InspectDetail>()
				.eq(InspectDetail::getAbBillNo, abBillNo));
		//查询源单编号
		Receivedetail receivedetail = receivedetailDao.selectOne(new LambdaQueryWrapper<Receivedetail>()
				.eq(Receivedetail::getBillNo, receiveBillNo));
		if (trueOrfalse.equals("0")) {
			detail.setReceiveBillNo(receiveBillNo);
			detail.setReveiveId(receivedetail.getId());
			res = inspectDetailService.saveOrUpdate(detail);
		}else{
			List<InspectDetail> detailList = inspectDetailDao.selectList(new LambdaQueryWrapper<InspectDetail>()
					.eq(InspectDetail::getBillNo,detail.getBillNo()));
			for (InspectDetail list :detailList){
				list.setReceiveBillNo(receiveBillNo);
				list.setReveiveId(receivedetail.getId());
			}
			res = inspectDetailService.saveOrUpdateBatch(detailList);
		}
		return res;
	}

	/**
	 * 质检来料检验单
	 * @param
	 * @return
	 */
	@Override
	public boolean auditInspect(Long user_id, String userName,Map<String, Object> map) throws Exception{
		String billNo = VtuzxUtil.getString(map,"billNo");
		//查询表头数据，准备修改质检状态以及质检人
		QueryWrapper<Inspect> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("billNo",billNo);
		Inspect inspect= inspectDao.selectOne(queryWrapper);
		if (inspect == null){
			throw new RuntimeException("单号错误请重试");
		}
		inspect.setStatus("audit");
		inspect.setInspectUser(userName);
		inspect.setInspectDate(new Date());
		Boolean sendRes = false;//是否发送待办通知
		//查询表体，准备修改质检合格与不合格数量
		QueryWrapper<PurInspectDetail> purInspectDetailQueryWrapper = new QueryWrapper<>();
		purInspectDetailQueryWrapper.eq("billNo",billNo);
		List<PurInspectDetail> purInspectDetailList = purInspectDetailDao.selectList(purInspectDetailQueryWrapper);
		List<PurInspectDetail> savePurInList = new ArrayList<>();//需要生成采购入库的质检单集合
		for (PurInspectDetail detail :purInspectDetailList){
			//如果收料通知单号没有值的话不让传
			if (detail.getReceiveBillNo() == null || VtuzxUtil.isEmpty(detail.getReceiveBillNo())){
				throw new RuntimeException("异常处理单还未处理，不允许审核");
			}
			Double qualifiedQty = detail.getQualifiedQty();//质检数量
			Double inspectQty = detail.getInspectQty();
			Double unqualifiedQty = detail.getUnqualifiedQty();//不合格数量
			if (unqualifiedQty != 0){
				detail.setResult("不合格");
			}else {
				detail.setResult("合格");
			}
			//只要有质检不合格的就通知采购
			if(unqualifiedQty >0){
				yzjService.sendMsgToPur(detail);

			}
			//质检全部不合格不生成采购入库单
			if (inspectQty > unqualifiedQty){
				savePurInList.add(detail);
			}


		}

		if (savePurInList.size() > 0 && null != savePurInList){
			try {
				//质检后生成采购入库单
				Boolean purInRes = purInService.createPurIn(inspect,savePurInList,userName,user_id);
			} catch (Exception e){
				throw e;
			}
		}


		boolean resdetail = purInspectDetailService.saveOrUpdateBatch(purInspectDetailList);

		boolean reshead = inspectServicel.saveOrUpdate(inspect);
		return reshead & resdetail;

	}


	
}